package day19.pack3;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/*
jdk的原生代理：
   限制： 被代理的对象，必须要有接口
 */
public class DynamicProxy implements InvocationHandler {
    public DynamicProxy(Object targer) {
        this.targer = targer;
    }
    public Object targer;

    /**
     * 泛型返回值，左边用什么接，就返回什么类型。
     * 比Object返回值的好处是：不用强制转换了
     * @return Object 代理对象
     */
    public <T> T getProxyInstance() {
        return (T) Proxy.newProxyInstance(
                // 运行期间创建的匿名实现类，需要被类加载器加载
                targer.getClass().getClassLoader(),
                // 创建谁的匿名实现类的对象？ 创建被代理对象的接口的
                targer.getClass().getInterfaces(),
                // 重写了接口的方法，调用哪个对象的invoke方法呢？
                this
        );
    }


    /**
     * 这个方法就是代理对象重写接口抽象方法后，会调用该方法
     * @param proxy: 代理对象
     * @param method: 被代理对象的业务方法
     * @param args:   被代理对象的业务方法的参数
     * @return 返回具体被代理对象方法的返回值
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("前置增强：比如记录时间");
        Object res = null;
        try {
            res = method.invoke(targer, args);
        } catch (RuntimeException e) {
            rollback();
        }
        System.out.println("后置增强：比如记录操作");
        return res;
    }
}
